package com.lovesher.payment.service.plugin.alipay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.lovesher.payment.common.enums.NotifyMethod;
import com.lovesher.payment.common.enums.PayStatus;
import com.lovesher.payment.common.resposity.bean.AccountRechargeDTO;
import com.lovesher.payment.common.resposity.bean.PaymentSerial;
import com.lovesher.payment.common.resposity.bean.PluginConfig;
import com.lovesher.payment.common.resposity.bean.PluginConfigAttribute;
import com.lovesher.payment.common.resposity.bean.TransferDTO;
import com.lovesher.payment.common.resposity.bean.TransferResultDTO;
import com.lovesher.payment.service.resposity.bean.PaymentInterface;
import com.lovesher.payment.service.resposity.dao.PaymentSerialDao;
import com.lovesher.payment.service.resposity.mapper.PluginConfigAttributeMapper;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 支付宝转账
 * @link https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer
 */
@Component("aliTransferPlugin")
public class AliTransferPlugin extends PaymentInterface {


    private static Log log = LogFactory.getLog(AliTransferPlugin.class);

    @Resource
    private PluginConfigAttributeMapper pluginConfigAttributeMapper;

    @Resource
    private PaymentSerialDao paymentSerialDao;


    @Override
    public String getName() {
        return "支付宝转账支付";
    }

    @Override
    public String getVersion() {
        return "1.0";
    }

    @Override
    public String getAuthor() {
        return "tupx";
    }

    /**
     * 获取网址
     *
     * @return 网址
     */
    @Override
    public String getSiteUrl() {
        return "https://doc.open.alipay.com";
    }

    /**
     * 获取请求URL
     *
     * @return 请求URL
     */
    @Override
    public String getRequestUrl() {
        return "https://openapi.alipay.com/gateway.do";
    }

    /**
     * 获取请求方法
     *
     * @return 请求方法
     */
    @Override
    public RequestMethod getRequestMethod() {
        return RequestMethod.post;
    }

    /**
     * 获取请求字符编码
     *
     * @return 请求字符编码
     */
    @Override
    public String getRequestCharset() {
        return "UTF-8";
    }

    /**
     * 使用 Map按key进行排序
     *
     * @param map
     * @return
     */
    public static Map<String, Object> sortMapByKey(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        Map<String, Object> sortMap = new TreeMap<String, Object>();

        sortMap.putAll(map);

        return sortMap;
    }

    @Override
    public Map<String, String> getParameterMap(AccountRechargeDTO accountRechargeDTO, String serialSn) {
        return null;
    }

    @Override
    public Boolean queryOrderResult(PaymentSerial paymentSerial) {
        log.info("aliTransferPlugin queryOrderResult start..."+ JSONObject.toJSONString(paymentSerial));
        PluginConfig pluginConfig = getPluginConfig();
        // 数据库中获取支付相关参数
        Map<String, Object> pluginConfigMap = getPluginConfigMap(pluginConfig);
        AlipayClient alipayClient = new DefaultAlipayClient(getRequestUrl(),pluginConfigMap.get("app_id").toString(),pluginConfigMap.get("private_key").toString(),
                "json",this.getRequestCharset(),pluginConfigMap.get("alipay_public_key").toString(),AlipayConfig.SIGN_TYPE);

        AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
        /**
         * 业务参数
         */
        Map<String, Object> bizContent = new HashMap<String, Object>();

        // 商户转账唯一订单号
        bizContent.put("out_biz_no", paymentSerial.getOrderSn());
        bizContent.put("order_id", paymentSerial.getTradeNo());
        request.setBizContent(JSON.toJSONString(bizContent));
        try{
            AlipayFundTransOrderQueryResponse response = alipayClient.execute(request);
            log.info(JSON.toJSONString(response));
            if(response.isSuccess() && response.getStatus().equalsIgnoreCase("SUCCESS")){

                log.info(paymentSerial.getOrderSn() + " 查询调用成功");
                return  true;
            } else {
                log.info(paymentSerial.getOrderSn() + " 查询调用成功");
                return  false;
            }
        }catch (Exception e){
            return  false;
        }
    }

    @Override
    public Map<String, Object> verifyNotify(String sn, NotifyMethod notifyMethod, HttpServletRequest request, PaymentSerial paymentSerial) {
        return null;
    }

    @Override
    public String getNotifyMessage(String sn, NotifyMethod notifyMethod, HttpServletRequest request) {
        return null;
    }

    @Override
    public Integer getTimeout() {
        return null;
    }

    @Override
    public void paySucess(PaymentSerial paymentSerial, String returnText, PayStatus payStatus, HttpServletRequest request) {

    }

    @Override
    public TransferResultDTO transfer(TransferDTO transferDTO) {
    	TransferResultDTO resultDTO = new TransferResultDTO();
    	resultDTO.setSuccess(false);
        log.info("aliTransferPlugin getParameter start..."+ JSONObject.toJSONString(transferDTO));
        PluginConfig pluginConfig = getPluginConfig();
        // 数据库中获取支付相关参数
        Map<String, Object> pluginConfigMap = getPluginConfigMap(pluginConfig);

        /**
         * 业务参数
         */
        Map<String, Object> bizContent = new HashMap<String, Object>();

        // 商户转账唯一订单号
        bizContent.put("out_biz_no", transferDTO.getOrderSn());

        // 收款方账户类型。可取值：
        //1、ALIPAY_USERID：支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。
        //2、ALIPAY_LOGONID：支付宝登录号，支持邮箱和手机号格式
        bizContent.put("payee_type", "ALIPAY_LOGONID");

        // 收款方账户。与payee_type配合使用。付款方和收款方不能是同一个账户。
        bizContent.put("payee_account", transferDTO.getPayeeAccount());

        // 转账金额，单位：元。
        bizContent.put("amount", transferDTO.getMoney().setScale(2, BigDecimal.ROUND_DOWN));

        // 付款方姓名（最长支持100个英文/50个汉字）。显示在收款方的账单详情页。如果该字段不传，则默认显示付款方的支付宝认证姓名或单位名称。
        //bizContent.put("payer_show_name", "");

        // 收款方真实姓名（最长支持100个英文/50个汉字）。
        //如果本参数不为空，则会校验该账户在支付宝登记的实名是否与收款方真实姓名一致。
        bizContent.put("payee_real_name", transferDTO.getRealname());

        //转账备注（支持200个英文/100个汉字）。
        //当付款方为企业账户，且转账金额达到（大于等于）50000元，remark不能为空。收款方可见，会展示在收款用户的收支详情中。
        bizContent.put("remark", transferDTO.getRemark() == null?"[章鱼哥]转账" + bizContent.get("amount") + "元":transferDTO.getRemark());
        log.info("【订单:" + transferDTO.getOrderSn() + "userId" + transferDTO.getUserId() + "】封装参数成功...");
        AlipayClient alipayClient = new DefaultAlipayClient(getRequestUrl(),pluginConfigMap.get("app_id").toString(),pluginConfigMap.get("private_key").toString(),
                "json",this.getRequestCharset(),pluginConfigMap.get("alipay_public_key").toString(),AlipayConfig.SIGN_TYPE);
        AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        request.setBizContent(JSON.toJSONString(bizContent));
        try {
            AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
            resultDTO.setResultMessage(JSON.toJSONString(response));
            log.info(JSON.toJSONString(response));
            if(response.isSuccess()){
                log.info("订单:" + transferDTO.getOrderSn() + "userId" + transferDTO.getUserId() + "调用成功");
                resultDTO.setSuccess(true);
                resultDTO.setResultMessage(response.getMsg());
                resultDTO.setResultCode(response.getCode());
                resultDTO.setTradeNo(response.getOrderId());
                return  resultDTO;
            }else{
            	resultDTO.setResultMessage(response.getSubMsg());
                resultDTO.setResultCode(response.getSubCode());
                return  resultDTO;
            }
        }catch (Exception e){
            log.info("订单:" + transferDTO.getOrderSn() + "userId" + transferDTO.getUserId() + "调用失败" , e);
        }
        return  resultDTO;
    }

    private Map<String, Object> getPluginConfigMap(PluginConfig pluginConfig) {
        Map<String, Object> pluginConfigMap = new HashMap<String, Object>();
        List<PluginConfigAttribute> pluginConfigAttributes = pluginConfigAttributeMapper
                .findByPluginId(pluginConfig.getId());
        for (int i = 0; i < pluginConfigAttributes.size(); i++) {
            PluginConfigAttribute pluginConfigAttribute = pluginConfigAttributes.get(i);
            pluginConfigMap.put(pluginConfigAttribute.getName(), pluginConfigAttribute.getAttributes());
        }
        return pluginConfigMap;
    }

    /**
     * 构造签名
     *
     * @param params
     * @param pluginConfigMap
     * @return
     * @throws UnsupportedEncodingException
     */
    public String createSign(Map<String, String> params, Map<String, Object> pluginConfigMap) {
        return AliRSA.sign(params,pluginConfigMap.get("private_key").toString(), this.getRequestCharset());
    }

}
